home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2007 January, February, March & April
/
Chip-Cover-CD-2007-02.iso
/
Pakiet bezpieczenstwa
/
mini Pentoo LiveCD 2006.1
/
mpentoo-2006.1.iso
/
livecd.squashfs
/
usr
/
sbin
/
ndiswrapper
< prev
next >
Wrap
Text File
|
2006-05-11
|
23KB
|
1,015 lines
#!/usr/bin/perl
#/*
#* Copyright (C) 2005 Pontus Fuchs, Giridhar Pemmasani
#*
#*
#* This program is free software; you can redistribute it and/or modify
#* it under the terms of the GNU General Public License as published by
#* the Free Software Foundation; either version 2 of the License, or
#* (at your option) any later version.
#*
#* This program is distributed in the hope that it will be useful,
#* but WITHOUT ANY WARRANTY; without even the implied warranty of
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#* GNU General Public License for more details.
#*
#*/
#use strict;
use Fcntl ':mode';
use File::Basename;
use File::Copy;
use File::Path;
my $WRAP_PCI_BUS = 5;
my $WRAP_PCMCIA_BUS = 8;
my $WRAP_USB_BUS = 15;
my @sections;
my %strings;
my %version;
my $driver_name;
my $confdir = "/etc/ndiswrapper";
my $instdir;
my %fuzzlist;
my %buslist;
# bustype is either PCI or USB, whereas BusType used in INF file can
# be different
my $bus;
my $classguid;
#Blacklist of files not to install.
my @copy_blacklist;
#Fixup list for parameters.
my %param_fixlist = ("EnableRadio|0" => "EnableRadio|1",
"IBSSGMode|0" => "IBSSGMode|2",
"PrivacyMode|0" => "PrivacyMode|2",
"AdhocGMode|1" => "AdhocGMode|0");
if(@ARGV < 1) {
usage();
exit();
}
my $modconf;
if (`uname -r` =~ /(\d+)\.(\d+)\.(\d+)/) {
if ($2 > 4) {
if (-d "/etc/modprobe.d") {
$modconf = "/etc/modprobe.d/ndiswrapper"
} else {
$modconf = "/etc/modprobe.conf"
}
} else {
if (-d "/etc/modutils") {
$modconf = "/etc/modutils/ndiswrapper";
} else {
$modconf = "/etc/modules.conf";
}
}
}
my $res;
if($ARGV[0] eq "-i" and @ARGV == 2) {
$res = install($ARGV[1]);
} elsif($ARGV[0] eq "-d" and @ARGV == 3) {
$res = devid_driver($ARGV[1], $ARGV[2]);
} elsif($ARGV[0] eq "-e" and @ARGV == 2) {
$res = remove($ARGV[1]);
} elsif($ARGV[0] eq "-l" and @ARGV == 1) {
$res = list();
} elsif($ARGV[0] eq "-m" and @ARGV == 1) {
$res = modalias();
} elsif($ARGV[0] eq "-v" and @ARGV == 1) {
printf "utils "; system("/sbin/loadndisdriver -v");
printf "driver ";
system("modinfo ndiswrapper | grep -E '^version|^vermagic'");
$res = 0;
} elsif($ARGV[0] eq "-da" and @ARGV == 1) {
$res = genmoddevconf(0);
} elsif($ARGV[0] eq "-di" and @ARGV == 1) {
$res = genmoddevconf(1);
} else {
usage();
exit();
}
exit $res;
sub usage {
print "Usage: ndiswrapper OPTION\n\n" .
"Manage ndis drivers for ndiswrapper.\n" .
"-i inffile Install driver described by 'inffile'\n" .
"-d devid driver Use installed 'driver' for 'devid'\n" .
"-e driver Remove 'driver'\n" .
"-l List installed drivers\n" .
"-m Write configuration for modprobe\n" .
"-da Write module alias configuration for all devices\n" .
"-di Write module install configuration for all devices\n" .
"-v Report version information\n" .
"\n\nwhere 'devid' is either PCIID or USBID of the form XXXX:XXXX\n";
}
sub install {
my $inf = shift;
$driver_name = lc($inf);
$driver_name =~ s/\.inf//;
$driver_name = basename($driver_name);
$instdir = dirname($inf);
chomp($instdir);
chomp($driver_name);
if (isInstalled($driver_name)) {
print "$driver_name is already installed. Use -e to remove it\n";
return -1;
}
if (opendir(DH, $confdir)) {
closedir(DH);
} else {
mkdir($confdir);
}
print "Installing $driver_name\n";
if (!mkdir("$confdir/$driver_name")) {
print "Unable to create directory $confdir/$driver_name." .
"Make sure you are running as root\n";
return -1;
}
loadinf($inf);
initStrings();
parseVersion();
copy("$inf", "$confdir/$driver_name/$driver_name.inf") or
die "couldn't copy $inf";
processPCIFuzz();
}
sub isInstalled {
my $installed;
my $name = shift;
my $stat = (stat("$confdir"))[2];
if (!S_ISDIR($stat)) {
return 0;
}
open(LS, "ls -1 $confdir|");
while(my $f = <LS>) {
chomp($f);
$stat = (stat("$confdir/$f"))[2];
if (S_ISDIR($stat) and $name eq $f) {
$installed = 1;
}
}
close(LS);
return $installed;
}
sub remove {
my $name = shift;
if (!isInstalled($name)) {
print "Driver $name is not installed." .
"Use -l to list installed drivers\n";
return;
}
rmtree("$confdir/$name", 0, 1);
}
sub devid_driver {
my $devid = shift;
my $driver = shift;
my $done = 0;
$devid = uc($devid);
if (!($devid =~ /[0-9A-Z]{4}:[0-9A-Z]{4}/)) {
print "'$devid' is not a valid device ID\n";
return;
}
open(LS, "ls -1 $confdir/$driver/ |");
while (my $f = <LS>) {
chomp($f);
if ($f =~ /\.([0-9A-F]+).conf$/) {
symlink("$f", "$confdir/$driver/$devid.$1.conf");
print "Driver '$driver' is used for '$devid'\n";
$done = 1;
last;
}
}
close(LS);
if ($done == 0) {
print "Driver '$driver' is not installed properly!\n";
}
return;
}
sub genmoddevconf {
my $mode = shift;
my $vendor, $device, $subvendor, $subdevice, $bustype, $busid;
my $line;
my $moddevconf;
if (-d "/etc/modprobe.d") {
$moddevconf = "/etc/modprobe.d/ndiswrapper";
} elsif (-d "/etc/modules.d") {
$moddevconf = "/etc/modules.d/ndiswrapper";
} else {
$moddevconf = "/etc/ndiswrapper/ndiswrapper";
}
if (!open(CONF, "| sort >$moddevconf")) {
print "Unable to create modules alias file $moddevconf\n";
return -1;
}
open(LS, "ls -1 $confdir|");
while (my $driver = <LS>) {
chomp($driver);
my $stat = (stat("$confdir/$driver"))[2];
if (S_ISDIR($stat)) {
open(LS2, "ls -1 $confdir/$driver/ |");
while (my $file = <LS2>) {
chomp ($file);
my $line = $file;
if ($file =~ s/.conf//) {
if ($file =~ /(.{4}):(.{4}):(.{4}):(.{4})\.([05F])/) {
$vendor = $1;
$device = $2;
$subvendor = "0000$3";
$subdevice = "0000$4";
$busid = "$5";
} elsif($file =~ /(.{4}):(.{4})\.([05F])/) {
$vendor = $1;
$device = $2;
$subvendor = "*";
$subdevice = "*";
$busid = "$3";
}
my $devstring;
if ($busid eq "0" or $busid eq "F") {
$devstring = sprintf("usb:v%sp%sd*dc*dsc*dp*ic*isc*ip*",
$vendor, $device);
} elsif ($busid eq "5") {
$devstring = sprintf("pci:v0000%sd0000%ssv%ssd%sbc*sc*i*",
$vendor, $device, $subvendor,
$subdevice);
} else {
print stderr "wrong bustype ($busid) for " .
"configuration file $line - ignoring it\n";
next;
}
if ($mode == 0) {
printf CONF "alias %s ndiswrapper\n", $devstring;
} else {
printf CONF "install %s /sbin/modprobe ndiswrapper\n",
$devstring;
}
}
}
close(LS2);
}
}
close(CONF);
close(LS);
print "Module configuration information is stored in $moddevconf\n";
return 0;
}
sub list {
my $s;
my $cards = getPresentCards();
if (!$cards) {
print "WARNING: Cannot locate lspci and lsusb." .
"Unable to see if hardware is present.\n";
}
my $stat = (stat("$confdir"))[2];
if (!S_ISDIR($stat)) {
print "No drivers installed\n$s";
return;
}
open(LS, "ls -1 $confdir|");
while (my $f = <LS>) {
chomp($f);
my $stat = (stat("$confdir/$f"))[2];
if (S_ISDIR($stat)) {
$s .= "$f\t".installStatus($cards, $f)."\n";
}
}
if ($s) {
print "Installed drivers:\n$s";
} else {
print "No drivers installed\n$s";
}
close(LS);
}
sub modalias {
my $alias = 0;
open(MODPROBE, "modprobe -c|");
while (my $line = <MODPROBE>) {
if ($line =~ /^alias\s.+\sndiswrapper/) {
print "modprobe config already contains alias directive\n\n";
$alias = 1;
} elsif ($line =~ /^install\s.*ndiswrapper/) {
printf stderr "module configuration contains directive $line;" .
"you should delete that";
} elsif ($line =~ /^post-install\s+ndiswrapper/) {
printf stderr "module configuration contains directive $line;" .
"you should delete that";
}
}
close(MODPROBE);
if ($alias) {
return;
}
print "Adding \"alias wlan0 ndiswrapper\" to $modconf\n";
system("echo \"alias wlan0 ndiswrapper\" >>$modconf");
if (-x "/sbin/update-modules") {
system("/sbin/update-modules");
}
}
sub getPresentCards {
#01:00.0 Class 0300: 1002:4c66 (rev 01)
# Subsystem: 1043:1732
my @cards;
my @lspci = ("/sbin/lspci", "/usr/sbin/lspci", "lspci");
for (my $i = 0; $i < @lspci; $i++) {
if (open(LSPCI, "$lspci[$i] -vn|")) {
my $card;
while(my $line = <LSPCI>) {
if($line =~ /^[0-9]+.*:\s(.{4}):(.{4}).*/) {
my %c;
$card = \%c;
$card->{vendor} = $1;
$card->{device} = $2;
}
if ($line =~ /.+Subsystem:\s*(.{4}):(.{4}).*/) {
$card->{subvendor} = $1;
$card->{subdevice} = $2;
push(@cards, $card);
}
}
last;
}
}
my @lsusb = ("/sbin/lsusb", "/usr/sbin/lsusb", "lsusb");
for(my $i = 0; $i < @lsusb; $i++) {
if (open(LSUSB, "$lsusb[$i] |")) {
my $card;
while(my $line = <LSUSB>) {
if($line =~ /.*: ID\s(.{4}):(.{4}).*/) {
my %c;
$card = \%c;
$card->{vendor} = $1;
$card->{device} = $2;
push(@cards, $card);
}
}
last;
}
}
return \@cards;
}
sub installStatus {
my $cards = shift;
my $driver = shift;
my $sys = 0;
my $conf = 0;
my $inf = 0;
if (!$cards) {
return;
}
open(LS2, "ls -1 $confdir/$driver|");
while (my $device = <LS2>) {
chomp($device);
my $d = $device;
$sys = 1 if $d =~ /\.sys$/;
$inf = 1 if $d =~ /\.inf$/;
$conf = 1 if $conf eq 0 and $d =~ /\.conf$/;
$d =~ s/.conf//;
if ($d =~ /(.{4}):(.{4}):(.{4}):(.{4})/) {
for (my $i = 0; $$cards[$i]; $i++) {
if ($$cards[$i]->{vendor} == $1 and
$$cards[$i]->{device} == $2 and
$$cards[$i]->{subvendor} == $3 and
$$cards[$i]->{subdevice} == $4) {
$conf = 3;
last;
}
}
} elsif($d =~ /(.{4}):(.{4})/) {
for (my $i = 0; $$cards[$i]; $i++) {
if ($$cards[$i]->{vendor} == $1 and
$$cards[$i]->{device} == $2) {
my $stat = (lstat("$confdir/$driver/$device"))[2];
if (S_ISLNK($stat)) {
$conf = 2;
} else {
$conf = 3;
}
last;
}
}
}
}
close(LS2);
my $ret;
if ($sys eq 0 || $inf eq 0 || $conf eq 0) {
$ret = "invalid driver!";
} else {
$ret = "\tdriver installed " if $conf eq 1;
$ret = "\tdriver installed, hardware present " if $conf eq 2;
$ret = "\tdriver installed, hardware present " if $conf eq 3;
}
return $ret;
}
#
# Create symlink for PCI general device if not existing
#
sub processPCIFuzz {
my @devs = keys(%fuzzlist);
for (my $i = 0; $i < @devs; $i++) {
my $dev = $devs[$i];
if ($dev ne $fuzzlist{$dev}) {
my $bt = $buslist{$dev};
my $src = "$confdir/$driver_name/$fuzzlist{$dev}.$bt.conf";
my $dst = "$confdir/$driver_name/$dev.$bt.conf";
symlink("$src", "$dst");
}
}
}
#
# Collect a list of supported PCI-Id's so we can add fuzzy entries if needed.
#
sub addPCIFuzzEntry {
my $vendor = shift;
my $device = shift;
my $subvendor = shift;
my $subdevice = shift;
my $bus = shift;
my $s = "$vendor:$device";
if (!$subvendor or !$fuzzlist{$s}) {
my $s2 = $s;
if ($subvendor) {
$s2 .= ":$subvendor:$subdevice";
}
$fuzzlist{$s} = $s2;
$buslist{$s} = $bus;
}
}
sub parseVersion {
my $s = getSection("version");
if (!$s) {
return;
}
my @lines = split("\n", $s->{data});
for (my $i = 0; $i < @lines; $i++) {
(my $key, my $val) = getKeyVal($lines[$i]);
if ($key eq "Provider") {
$val =~ s/"(.+)"/$1/;
$version{$key} = $val;
}
if ($key eq "DriverVer") {
$val =~ s/"(.+)"/$1/;
$version{$key} = $val;
}
if ($key eq "ClassGUID") {
$val =~ s/\{(.+)\}/$1/;
$classguid = lc($val);
}
}
parseMfr();
}
#
# Parse the [Manufacturer] section.
#
sub parseMfr {
#Examples:
#Vendor
#Vendor,ME,NT,NT.5.1
#Vendor.NTx86
my $manu = getSection("manufacturer");
if (!$manu) {
return -1;
}
my @lines = split("\n", $manu->{data});
for (my $i = 0; $i < @lines; $i++) {
my $line = remComment($lines[$i]);
(my $key, my $val) = getKeyVal($line, "=");
if ($key eq $version{"Provider"}) {
$strings{$key} = trim($val);
}
if ($val) {
my $section;
my @flavours = map { stripquotes(trim($_)) } split(",", $val);
my $flavour = "";
if(@flavours == 1) {
#Vendor
$section = $flavours[0];
} else {
#Vendor,flavour1, flavour2 etc;
for (my $i = 1; $i < @flavours; $i++) {
my $flav = $flavours[$i];
$flav =~ s/\s*(\S+)\s*/$1/;
if (uc($flav) eq "NT.5.1") {
#This is the best (XP)
$section = $flavours[0] . "." . $flav;
$flavour = $flav;
} elsif (substr(uc($flav),0,2) eq "NT" and
$section eq "") {
#This is the second best (win2k)
$section = $flavours[0] . "." . $flav;
$flavour = $flav;
}
}
}
my $res = parseVendor($flavour, $section);
if ($res) {
return $res;
}
}
}
}
#
# Parse a vendor section. This section contains the device-ids.
# Each poiting to a section with config info.
#
sub parseVendor {
my $flavour = shift;
my $vendor_name = shift;
my $vend = getSection($vendor_name);
if (!$vend) {
print "no vendor\n";
return -1;
}
my @lines = split("\n", $vend->{data});
for (my $i = 0; $i < @lines; $i++) {
my $line = remComment($lines[$i]);
(my $name, my $val) = getKeyVal($line, "=");
if ($val) {
my $section;
my $id;
($section, $id) = split(",", $val);
$section = trim($section);
$id = substStr(trim($id));
my $bt, $vendor, $device, $subvendor, $subdevice;
($bus, $vendor, $device, $subvendor, $subdevice) = parseID($id);
if ($vendor) {
parseDevice($flavour, $section, $vendor, $device,
$subvendor, $subdevice);
}
}
}
}
#
# This section contains pointers to registry sections and copyfiles sections.
#
sub parseDevice {
my $flavour = shift;
my $device_sect = shift;
my $device = shift;
my $vendor = shift;
my $subvendor = shift;
my $subdevice = shift;
my $dev;
# for RNDIS INF file (for USR5420), vendor section names device
# section as RNDIS.NT.5.1, but copyfiles section is RNDIS.NT, so
# first strip flavour from device_sect and then look for matching
# section
if ($device_sect eq "RNDIS.NT.5.1") {
$dev = getSection("RNDIS.NT");
}
if (!$dev) {
$dev = getSection("$device_sect.$flavour");
}
if (!$dev) {
$dev = getSection("$device_sect.NT");
}
if (!$dev) {
$dev = getSection("$device_sect.NTx86");
}
if (!$dev) {
$dev = getSection("$device_sect");
}
if (!$dev) {
print "no dev $device_sect $flavour\n";
return -1;
}
# print "$device:$vendor:$subvendor:$subdevice $flavour\n";
my @copy_files;
my $addreg;
my @lines = split("\n", $dev->{data});
for (my $i = 0; $i < @lines; $i++) {
my $line = $lines[$i];
$line =~ s/^;\s*//;
$line = trim(remComment($line));
(my $key, my $val) = getKeyVal($line, "=");
if ($key) {
if (lc($key) eq "addreg") {
$addreg = $val;
} elsif (lc($key) eq "copyfiles") {
push @copy_files, $val;
} elsif ($key eq "BusType") {
$strings{$key} = $val;
}
}
}
my $filename = "$device:$vendor";
if ($subvendor) {
$filename .= ":$subvendor:$subdevice"
}
my $bt = sprintf("%X", $bus);
$filename .= ".$bt.conf";
if ($bus == $WRAP_PCI_BUS || $bus == $WRAP_PCMCIA_BUS) {
addPCIFuzzEntry($device, $vendor, $subvendor, $subdevice, $bt);
}
if (!open(CONF, ">$confdir/$driver_name/$filename")) {
print "Unable to create file $filename";
return -1;
}
my $ver=$version{"DriverVer"};
my $provider=$version{"Provider"};
my $providerstring = stripquotes(substStr(trim($provider)));
printf CONF "NdisVersion|0x50001\n";
printf CONF "Environment|1\n";
if ($strings{"BusType"} ne "") {
printf CONF "BusType|$strings{\"BusType\"}\n";
}
printf CONF "class_guid|$classguid\n";
printf CONF "mac_address|XX:XX:XX:XX:XX:XX\n";
printf CONF "driver_version|$providerstring,$ver\n";
printf CONF "\n";
close(CONF);
if (!open(CONF, "|sort|uniq >>$confdir/$driver_name/$filename")) {
print "Unable to create file $filename";
return -1;
}
my @addregs = split(",", $addreg);
for (my $i = 0; $i < @addregs; $i++) {
my $reg = trim($addregs[$i]);
addReg($reg);
}
for (my $i = 0; $i < @copy_files; $i++) {
my @copy_sec = split(",", $copy_files[$i]);
for (my $j = 0; $j < @copy_sec; $j++) {
my $file = trim($copy_sec[$j]);
copyfiles($file);
}
}
close(CONF);
}
#
# Process a copyfiles section.
#
sub copyfiles {
my $copy_name = shift;
my $copy;
if ($copy_name =~ /^\@/) {
$copy_name =~ s/^\@//;
return copy_file($copy_name);
}
$copy = getSection($copy_name);
if (!$copy) {
printf "Parse error in inf. Unable to find section $copy_name\n";
return -1;
}
my @lines = split("\n", $copy->{data});
for (my $i = 0; $i < @lines; $i++) {
my $line = $lines[$i];
$line = trim($line);
last if ($line =~ /^\[/);
my @files = split(",", $line);
for (my $j = 0; $j < @files; $j++) {
my $file = $files[$j];
$file = trim($file);
if ($file and length($file) > 0) {
copy_file($file);
}
}
}
return 0;
}
sub copy_file {
my $file = shift;
$file =~ s/^;//;
$file = trim(remComment($file));
$file =~ s/,+.*//;
$file = trim($file);
my $nocopy = 0;
for (my $k = 0; $k < @copy_blacklist; $k++) {
if ($copy_blacklist[$k] eq lc($file)) {
$nocopy = 1;
}
}
my $dir = finddir($file);
if ($dir) {
$dir = findfile("", $dir);
}
my $realname = findfile($dir, $file);
if ($realname) {
my $newname = lc($realname);
if ($dir) {
$realname = "$dir/$realname";
}
if (!$nocopy) {
copy("$instdir/$realname", "$confdir/$driver_name/$newname");
chmod(0644, "$confdir/$driver_name/$newname");
}
}
}
sub finddir {
my $filename = shift;
my $sourcedisksfiles = getSection("sourcedisksfiles");
if (!$sourcedisksfiles) {
return "";
}
my @lines = split("\n", $sourcedisksfiles->{data});
for (my $i = 0; $i < @lines; $i++) {
my $line = trim(remComment($lines[$i]));
$line =~ /(.+)=.+,+(.*)/;
my $file = trim($1);
my $dir = trim($2);
if ($file and $dir and lc($filename) eq lc($file)) {
return $dir;
}
}
return "";
}
#
# Find a file in a case-insensitive way.
#
sub findfile {
my $dir = shift;
my $file = shift;
if (!opendir(DIR, "$instdir/$dir")) {
print "Unable to open $instdir\n";
return "";
}
my @allfiles = readdir(DIR);
for (my $i = 0; $i < @allfiles; $i++) {
if (lc($allfiles[$i]) eq lc($file)) {
closedir(DIR);
return $allfiles[$i];
}
}
closedir(DIR);
return "";
}
#
# This section contains pointers to the section with the parameters to be
# added to the registry.
#
sub addReg {
my $reg_name = shift;
my $reg = getSection($reg_name);
if (!$reg) {
printf "Parse error in inf. Unable to find section $reg_name\n";
return -1;
}
my $param;
my $type;
my $val;
my $found;
my $gotParam = 0;
my @lines = split("\n", $reg->{data});
for (my $i = 0; $i < @lines; $i++) {
my $line = trim(remComment($lines[$i]));
if ($line) {
$line =~ /([^,]*),([^,]*),([^,]*),([^,]*),(.*)/;
my $hkr = trim($1);
my $p1 = stripquotes(substStr(trim($2)));
my $p2 = stripquotes(substStr(trim($3)));
my $p3 = stripquotes(substStr(trim($4)));
my $p4 = stripquotes(substStr(trim($5)));
if ($p1) {
if($p1 =~ /ndi\\params\\(.+)/i) {
$1 =~ /(.+)\\.*/;
if ($1 ne $param) {
$found = 0;
$param = $1;
$type = "";
$val = "";
}
if (lc($p2) eq "type") {
$found++;
$type = $p4;
} elsif (lc($p2) eq "default") {
$found++;
$val = $p4;
}
if ($found == 2) {
$gotParam = 1;
}
}
} else {
$param = $p2;
$val = $p4;
$gotParam = 1;
}
if ($gotParam and $param ne "" and $param ne "BusType") {
my $s = "$param|$val";
if ($param_fixlist{"$s"}) {
my $sOld = $s;
$s = $param_fixlist{"$s"};
print "Forcing parameter $sOld to $s\n";
}
print CONF "$s\n";
$param = "";
$gotParam = 0;
}
}
}
}
sub substStr {
my $s = shift;
if ($s =~ /^\%(.+)$\%/) {
return getString($1);
}
return $s;
}
#
# Parse a device-id line.
#
sub parseID {
my $s = uc(shift);
if ($s =~ /PCI\\VEN_(\w+)&DEV_(\w+)&SUBSYS_(\w{4})(\S{4})/) {
return ($WRAP_PCI_BUS, $1, $2, $4, $3);
} elsif ($s =~ /PCI\\VEN_(\w+)&DEV_(\w+)/) {
return ($WRAP_PCI_BUS, $1, $2);
} elsif ($s =~ /USB\\VID_(\w+)&PID_(\w+)/) {
return ($WRAP_USB_BUS, $1, $2);
}
}
#
# remove whitsepace at front and end.
#
sub trim {
my $s = shift;
$s =~ s/^\s*//;
$s =~ s/\s*$//;
return $s;
}
sub stripquotes {
my $s = shift;
$s =~ s/"(.*)"/$1/;
return $s;
}
sub getKeyVal {
my $line = shift;
$line = remComment($line);
(my $key, my $val) = split("=", $line);
if ($line =~ /(.+)=(.+)/) {
return (trim($1), trim($2));
}
}
sub remComment {
my $s = shift;
$s=~ s/([^;]*);.*/$1/;
return $s;
}
#
# Initialize the string symbol table
#
sub initStrings {
my $s = getSection("strings");
if (!$s) {
return;
}
my @lines = split("\n", $s->{data});
for (my $i = 0; $i < @lines; $i++) {
(my $key, my $val) = getKeyVal($lines[$i]);
if ($key) {
$val =~ s/"(.+)"/$1/;
$strings{$key} = $val;
}
}
}
#
# fetch a string from the symbol table
#
sub getString {
my $s = shift;
return $strings{$s};
}
#
# Loacate a section.
#
sub getSection {
my $needle = shift;
for (my $i = 0; $i < @sections; $i++) {
if ( lc($sections[$i]->{name}) eq lc($needle)) {
return $sections[$i];
}
}
return 0;
}
#
# Load inf and split into different sections.
#
sub loadinf {
my $filename = shift;
my %def_section;
my $section = \%def_section;
if (!open(INF, $filename)) {
return -1;
}
my $i = 0;
$section->{name} = "none";
while (my $s = <INF>) {
#Convert from unicode
$s =~ s/\xff\xfe//;
$s =~ s/\0//g;
$s =~ s/\s*$//; #Remove trailing whitespace and \r
$s .= "\n";
if ($s =~ /^\[(.+)\]/) {
$sections[$i++] = $section;
my %new_section;
$section = \%new_section;
$section->{name} = $1;
} else {
$section->{data} .= $s;
}
}
$sections[$i++] = $section;
close(INF);
}
## Local Variables: ##
## cperl-indent-level: 4 ##
## End: ##